package ca.cbc.giscommon.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;

/**
 * =============================================
 * Copyright (c) 2011 Canadian Broadcasting Corporation.
 * All rights reserved.
 * <p/>
 * ca.cbc.medialib.util.HibernateUtil.java
 * =============================================
 * <p/>
 * PURPOSE:	Manages Hibernate Session Factory and Session
 * <p/>
 * =============================================
 * MODIFICATION		LOG	DATE		REASON / Change Request #
 * Liu Yang			Jun 22, 2011	Initial file creation
 * =============================================
 */
public class HibernateUtil {
    private static Logger logger = LoggerFactory.getLogger(HibernateUtil.class.getName());

    private static String configurationFile;
    private static SessionFactory sessionFactory;

    /**
     * Create the Session Factory if It's not null
     */
    public static void createSessionFactory() throws HibernateException {
        createSessionFactory(configurationFile);
    }

    /**
     * Create the Factory given the Configuration File.
     *
     * @param configFile
     * @return
     */
    public static void createSessionFactory(String configFile) throws HibernateException {
        configurationFile = configFile;
        if (sessionFactory == null) {
            logger.debug("No SessionFactory found, create session factory.");
            Configuration cfg = null;
            if (configurationFile == null)
                cfg = new Configuration().configure();
            else
                cfg = new Configuration().configure(configurationFile);
            sessionFactory = cfg.buildSessionFactory();
        }
    }

    /**
     * This method retrieves the Hibernate Session
     *
     * @return Hibernate Session
     */
    public static Session getSession() throws HibernateException {
        if (sessionFactory == null)
            createSessionFactory();
        Session currSession = sessionFactory.getCurrentSession();
        if (!currSession.isOpen()) { //in case of getting a closed session by getCurrentSession()
            logger.warn("Current session is closed, recreate SessionFactory");
            sessionFactory = null;
            createSessionFactory();
            currSession = sessionFactory.getCurrentSession();
        }
        return currSession;
    }

    /**
     * This method closes the Hibernate Session.
     */
    public static void shutdown() throws HibernateException {
        // Close caches and connection pools
        if (sessionFactory != null) {
            sessionFactory.close();
            sessionFactory = null;
            logger.debug("*** Hibernate session is now closed.");
        }
    }

    /**
     * Begin the Transaction
     */
    public static void beginTransaction() throws HibernateException {
        getSession().beginTransaction();
    }

    /**
     * Commit Transaction.
     */
    public static void commitTransaction() throws HibernateException {
        getSession().getTransaction().commit();
        logger.debug("Transaction commited.");
    }

    /**
     * Checks to see if current transaction is active
     *
     * @return
     */
    public static boolean isActiveTransaction() throws HibernateException {
        return getSession().getTransaction().isActive();
    }

    /**
     * Roll backs transaction.
     */
    public static void rollbackTransaction() throws HibernateException {
        getSession().getTransaction().rollback();
        getSession().close();
    }

    /**
     * Flush all transactions.
     */
    public static void flushAndClear() throws HibernateException {
        getSession().flush();
        getSession().clear();
    }

    /**
     * Retrieves configuration file.
     *
     * @return
     */
    public static String getConfigurationFile() {
        return configurationFile;
    }

    /**
     * Set configuration file.
     *
     * @param configurationFile
     */
    public static void setConfigurationFile(String configurationFile) {
        HibernateUtil.configurationFile = configurationFile;
    }
}
